package model

import (
	"errors"
	"time"

	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// 用户角色
type UserRole string

const (
	RoleCandidate   UserRole = "candidate"
	RoleInterviewer UserRole = "interviewer"
	RoleAdmin       UserRole = "admin"
)

// UserModel 用户模型
type UserModel struct {
	ID           int64     `gorm:"primaryKey;column:id" json:"id"`
	Email        string    `gorm:"uniqueIndex;size:100;not null" json:"email"`
	PasswordHash string    `gorm:"column:password_hash;size:100;not null" json:"-"`
	Name         string    `gorm:"size:100;not null" json:"name"`
	AvatarUrl    string    `gorm:"column:avatar_url;size:200" json:"avatar_url"`
	Role         string    `gorm:"size:20;not null;default:candidate" json:"role"`
	CreatedAt    time.Time `gorm:"autoCreateTime" json:"created_at"`
	UpdatedAt    time.Time `gorm:"autoUpdateTime" json:"updated_at"`
}

// TableName 设置表名
func (UserModel) TableName() string {
	return "users"
}

// UserStore 用户存储接口
type UserStore interface {
	// 查询操作
	FindOne(id int64) (*UserModel, error)
	FindByEmail(email string) (*UserModel, error)
	FindByRole(role string) ([]*UserModel, error)
	FindByIds(ids []int64) ([]*UserModel, error)
	List(limit, offset int64) ([]*UserModel, error)

	// 写入操作
	Insert(data *UserModel) error
	Update(data *UserModel) error
	Delete(id int64) error
}

// 错误定义
var (
	ErrNotFound = errors.New("record not found")
)

// defaultUserStore 默认用户数据存储
type defaultUserStore struct {
	db *gorm.DB
}

// NewUserStore 创建用户存储实例
func NewUserStore(db *gorm.DB) UserStore {
	return &defaultUserStore{
		db: db,
	}
}

// FindOne 根据ID查询单个用户
func (m *defaultUserStore) FindOne(id int64) (*UserModel, error) {
	var user UserModel
	result := m.db.First(&user, id)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, ErrNotFound
		}
		return nil, result.Error
	}
	return &user, nil
}

// FindByEmail 根据邮箱查询用户
func (m *defaultUserStore) FindByEmail(email string) (*UserModel, error) {
	var user UserModel
	result := m.db.Where("email = ?", email).First(&user)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, ErrNotFound
		}
		return nil, result.Error
	}
	return &user, nil
}

// FindByRole 根据角色查询用户列表
func (m *defaultUserStore) FindByRole(role string) ([]*UserModel, error) {
	var users []*UserModel
	result := m.db.Where("role = ?", role).Find(&users)
	if result.Error != nil {
		return nil, result.Error
	}
	return users, nil
}

// FindByIds 根据ID列表查询多个用户
func (m *defaultUserStore) FindByIds(ids []int64) ([]*UserModel, error) {
	var users []*UserModel
	result := m.db.Where("id IN ?", ids).Find(&users)
	if result.Error != nil {
		return nil, result.Error
	}
	return users, nil
}

// List 分页查询用户列表
func (m *defaultUserStore) List(limit, offset int64) ([]*UserModel, error) {
	var users []*UserModel
	result := m.db.Order("created_at DESC").Limit(int(limit)).Offset(int(offset)).Find(&users)
	if result.Error != nil {
		return nil, result.Error
	}
	return users, nil
}

// Insert 插入用户记录
func (m *defaultUserStore) Insert(data *UserModel) error {
	return m.db.Create(data).Error
}

// Update 更新用户记录
func (m *defaultUserStore) Update(data *UserModel) error {
	return m.db.Save(data).Error
}

// Delete 删除用户记录
func (m *defaultUserStore) Delete(id int64) error {
	return m.db.Delete(&UserModel{}, id).Error
}

// HashPassword 对密码进行哈希处理
func HashPassword(password string) (string, error) {
	hashedBytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return "", err
	}
	return string(hashedBytes), nil
}

// ComparePassword 比较密码和哈希值
func ComparePassword(hashedPassword, password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
	return err == nil
}
